package com.itheima.mapper;

import com.itheima.pojo.Emp;
import org.apache.ibatis.annotations.*;

import java.time.LocalDate;
import java.util.List;


/*
@Mapper 注解代表程序在运行的时候会自动的创建该接口的代理对象，并且会将这个代理对象放入到ioc容器中
弹幕：主要目的是为实现类提供一个统一的规范，不写具体的业务逻辑。只指定它们应该实现哪些方法。
 */
@Mapper
public interface EmpMapper {
    /*
    根据ID删除数据：
    这个注解来指定执行的是什么样的操作，查询是用@select，删除操作用@delete
    @insert，@update

    并且我们需要在调用这个SQL语句的时候，动态的把这个id值传入进来，怎么传呢：
        只有在调用这个接口方法的时候才会调用这个SQL语句，所以只需要在调用这个接口方法的时候，传递一个参数，
        这个参数就是这个id，然后在SQL语句执行的时候，把这个参数传递进来就行。
    那如何动态获取这个方法在被调用的时候传递过来的参数呢：
        要用mybatis中的参数占位符#{}的形式，{}里面写的就是这个参数的名字

    delete执行语句是由返回值的，只不过目前不需要，它的返回值表示此次操作影响的行数
     */
    @Delete("delete from db08_mybatis.emp where id = #{id}")
    public Integer delete(Integer id);


    /**
     * 推荐将多个参数直接封装到一个对象里面，在调用insert方法的时候，就不用传递七八个参数了
     * 只需要传递一个对象就可以了
     * 所以接下来就可以把这些字段替换成动态的，参数占位符#{}，大括号里面写的就是这个对象的属性
     * 记得换成驼峰命名
     *
     * 测试的时候，调用这个insert方法，里面传递一个员工对象，然后为这个员工对象的各个属性进行赋值操作，
     * 最终在执行insert方法的时候，就会执行这条insertSQL语句，并自动获取这个emp对象中的各个属性值
     */
/*    @Insert("insert into db08_mybatis.emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time) " +
            "values ('zengjihong','曾',1,'1.jpg',1,'2000-01-16',1,now(),now())")  */
    /*
    第一个参数useGeneratedKeys代表我们要获取到返回的主键值
    第二个参数代表我们返回来的主键值往哪个属性里面封装
     */
    @Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into db08_mybatis.emp (username, name, gender, image, job, entrydate, " +
            "dept_id, create_time, update_time) " +
            "values (#{username},#{name},#{gender},#{image},#{job},#{entrydate}," +
            "#{deptId},#{createTime},#{updateTime})")
    public void insert(Emp emp);


    //更新员工
    @Update("update db08_mybatis.emp set username=#{username},name=#{name},gender=#{gender}," +
            "image=#{image},job=#{job},entrydate=#{entrydate},dept_id=#{deptId}," +
            "update_time=#{updateTime} where id=#{id};")
    public void update(Emp emp);


    //查询员工信息，查询是有返回值的，可以把结果封装到员工对象中
/*    @Select("select * from db08_mybatis.emp where id=#{id}")
    public Emp getById(Integer id);*/

    //如果实体类属性名 和 数据库表查询返回的字段名不一致，不能自动封装。
    //deptId=null, createTime=null, updateTime=null 这三个字段没有封装进来
    //解决方法一：给字段起别名，让别名与实体类属性保持一致
    //@Select("select id, username, password, name, gender, image, job, entrydate, dept_id deptId," +
    //        " create_time createTime, update_time updateTime from db08_mybatis.emp where id=#{id}")
    //public Emp getById(Integer id);


    //方法二：手动结果映射，通过 @Results及@Result 进行手动结果映射。
/*
    @Results里面的values是 Result[] value() default {}; 是一个数组
    而result对象也是一个注解，一个 @Result注解就是用来映射一个字段和属性，
    在@Result中的第一个属性指的是表中的字段名，property指的是我们需要手动映射的字段封装到哪个属性

    老师说：非常臃肿繁琐，不怎么用
*/
/*    @Results({
        @Result(column = "dept_id",property = "deptId"),
        @Result(column = "create_time",property = "createTime"),
        @Result(column = "update_time",property = "updateTime")
    })
    @Select("select * from db08_mybatis.emp where id=#{id}")
    public Emp getById(Integer id);*/


    //方法三：开启mybatis的驼峰命名自动映射开关
    @Select("select * from db08_mybatis.emp where id=#{id}")
    public Emp getById(Integer id);


    //条件查询员工，查询结果可能是多条记录，所以要用list集合来封装
    //相比把这四个参数封装到一个对象，把这四个参数直接传递进来更加方便
    /*
    注意事项：name like '%#{name}%' 这样写是不行的，因为#{}是不能写在引号里面，因为#{}最终生成的是预编译的SQL，
    最终是要被问号?替代的，也就是name like '%?%'
    而?这个参数占位符是不能出现在引号之内的，所以这里是不能直接使用#{}的

    解决方法一：把#改为$，$是字符串拼接符号，不会生成预编译的SQL，而是直接和前后两个%进行拼接
    */
/*    @Select("select * from db08_mybatis.emp where name like '%${name}%' and gender = #{gender} and" +
            " entrydate between #{begin} and #{end} order by update_time desc")
    public List<Emp> list(String name, Short gender, LocalDate begin,LocalDate end);*/


    /*
    解决方法二：
    select * from emp where name like concat('%','张','%') and gender = 1 and
    entrydate between '2010-01-01' and '2020-01-01' order by update_time desc ;
    这个张就是页面传递过来的数据，只需要把这个张变成动态的，使用问号来占位，也就是
    name like concat('%','张','%')
    name like concat('%',？,'%')
    这样子这个问号占位符就不在引号里面了
     */
/*    @Select("select * from db08_mybatis.emp where name like concat('%',#{name},'%') and gender = #{gender} and" +
            " entrydate between #{begin} and #{end} order by update_time desc")
    public List<Emp> list(String name, Short gender, LocalDate begin,LocalDate end);*/

    //上面这个条件查询语句，现在从注解的方式改为xml文件的方式来写动态SQL语句：
    public List<Emp> list(String name, Short gender, LocalDate begin,LocalDate end);


    //动态的更新员工，把上面的更新员工代码改造一下：
    public void update2(Emp emp);


    //批量删除员工，那么形参里面怎么去封装多个id值，一般用数组或者集合来装：
    public void deleteByIds(List<Integer> ids);

}
